﻿#pragma once
// C++11Test20191121.cpp : 定义控制台应用程序的入口点。
//

#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <map>
#include <bitset>
#include <functional>
#include <memory>
#include <mutex>
#include <chrono>
#include <time.h>
#include <list>
#include <future>
#include <algorithm>
#include <iterator>
#include <queue>
#include <random>
#include <numeric>
#include <atomic>
#include <sstream>
#include <variant>
#include <optional>
#include <any>
#include <typeindex>
#include <ctime>
#include <iomanip>
#include <cstdlib>
#include <codecvt>
#include <fstream>
#include <random>
//#include <Windows.h>
using namespace std;
//并行运算库
#include <ppl.h>
using namespace concurrency;

namespace common_test
{

class MyClass
{
public:
	MyClass();
	MyClass(int v, string s);
	MyClass(const MyClass& obj)
		:MyClass(obj.val, obj.str)
	{


	}
	~MyClass();
	MyClass& operator =(const MyClass obj)
	{
		this->val = obj.val;
		this->str = obj.str;

		return *this;
	}
public:
	void print()
	{
		cout << val << "," << str << endl;
	}
public:
	int val = 0;
	string str{ "MyClass" };
};

MyClass::MyClass()
{
}

MyClass::~MyClass()
{
}

MyClass::MyClass(int v, string s)
	:val(v), str(s)
{
}

template<typename T> using array = std::vector<T>;

class MyClassExt : public MyClass
{
public:
	using MyClass::MyClass;
private:

};

class thread_pool
{
public:
	thread_pool(const thread_pool&) = delete;
	thread_pool& operator=(const thread_pool&) = delete;
public:
	thread_pool(int thread_sum) {
		for (int i = 0; i < thread_sum; i++)
			thread_group.push_back(std::thread([this]
				{
					while (!this->exit_flag) {
						std::function<void()> task;
						{
							std::unique_lock lock(lock_obj);
							notify.wait(lock, [this] { return !task_queue.empty() || this->exit_flag; });
							if (this->exit_flag)
								return;

							task = std::move(task_queue.front());
							task_queue.pop_front();
						}
						task();
					}
				}));
	}

	~thread_pool() {
		this->close();
	}

	void close() {
		{
			std::unique_lock lock(lock_obj);
			this->exit_flag = true;
		}
		notify.notify_all();
		for (auto& sp_thread : thread_group)
			sp_thread.join();

		thread_group.clear();
	}

	template<typename F, typename... Args>
	auto dispatch(F&& f, Args&&... args) {
		using return_type = decltype(f(args...));
		auto sp_task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
		std::future<return_type> furure = sp_task->get_future();
		{
			std::unique_lock lock(lock_obj);
			task_queue.emplace_back([sp_task] {(*sp_task)(); });

		}
		notify.notify_one();

		return furure;
	}
private:
	std::vector<std::thread> thread_group;
	bool exit_flag = false;
	std::mutex lock_obj;
	std::condition_variable notify;
	std::list<std::function<void()>> task_queue;
};

class ThreadPool
{
public:
	ThreadPool(int nThreadCnt)
		:m_nThreadCnt(nThreadCnt)
	{
		m_bExit = false;
	}

	ThreadPool()
	{

	}

	void Start()
	{
		for (int i = 0; i < m_nThreadCnt; i++)
		{
			m_vtThread.push_back(thread(&ThreadPool::WorkLoop, this, i));
		}
	}

	void Stop()
	{
		m_bExit = true;
		m_is_not_empty.notify_all();
		for (thread& td : m_vtThread)
		{
			td.join();
		}
	}

	void WorkLoop(int index)
	{
		while (!m_bExit)
		{
			std::unique_lock<std::mutex> lock(m_lock);

			m_is_not_empty.wait(lock, [this] {return !this->m_vtTask.empty(); });

			if (!m_vtTask.empty())
			{
				//cout << "thread index = " << index << endl;
				m_vtTask.front()();
				m_vtTask.pop_front();
			}

			lock.unlock();
		}

		std::unique_lock<std::mutex> lock(m_lock);
		cout << "thread index = " << index << "exit" << endl;
	}

	//在C++模板中，SFINEA规则是指”Substitution failure is not an error“(匹配失败不是错误)。
	//具体来说，就是当重载的模板参数展开时，如果展开导致一些类型不匹配，编译器并不报错。

	template<typename T>
	struct has_member_foo
	{
	private:
		template<typename U>
		static auto Check(int) -> decltype(std::declval<U>().foo(), std::true_type());
		template<typename U>
		static std::false_type Check(...);
	public:
		enum { value = std::is_same<decltype(Check<T>(0)), std::true_type>::value };
	};

	template<typename F, typename... Args>
	auto Dispatch(F&& f, Args&& ...args)->std::future<decltype(f(args...))>
	{
		std::unique_lock<std::mutex> lock(m_lock);
		using return_type = decltype(f(args...));

		auto task = std::make_shared<std::packaged_task<return_type()> >(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
			);
		std::future<return_type> future = task->get_future();

		m_vtTask.emplace_back(
			[task]()
			{
				(*task)();
			}
		);
		m_is_not_empty.notify_all();

		return future;
	}

private:
	typedef std::list<std::function<void(void)>> MyQueue;

	int m_nThreadCnt;
	std::mutex m_lock;
	MyQueue m_vtTask;
	vector<thread> m_vtThread;
	std::condition_variable m_is_not_empty;
	bool m_bExit;
};

template<typename T>
auto sum(T a, T b)->decltype(a + b)
{
	//std::this_thread::sleep_for(std::chrono::seconds(3));
	return a + b;
}

void thread_test()
{
	ThreadPool pool(thread::hardware_concurrency());
	pool.Start();
	std::future<int> ret = pool.Dispatch(sum<int>, 1, 2);
	cout << ret.get() << endl;
	pool.Stop();
}

void promise_test()
{
	std::packaged_task<int(int, int)> task(sum<int>);
	std::future<int> future = task.get_future();

	thread td(std::move(task), 3, 5);

	auto beg = std::chrono::system_clock::now();
	cout << "开始计算" << endl;
	cout << future.get() << endl;
	cout << "计算完毕" << endl;
	auto ts = std::chrono::system_clock::now() - beg;
	cout << "耗费时间：" << std::chrono::duration_cast<std::chrono::seconds>(ts).count() << endl;
	td.join();
	cout << "线程结束" << endl;
}

bool lesser(int lhs, int rhs)
{
	return lhs < rhs;
}

bool greate(int lhs, int rhs)
{
	return lhs > rhs;
}

void function_test()
{
	auto fun = std::bind(std::logical_and<bool>(), std::bind(lesser, 10, std::placeholders::_1), std::bind(greate, 20, std::placeholders::_1));
	//auto fun = std::bind(lesss, 10, std::bind(greate,20,std::placeholders::_1));
	//auto s = std::less<int>()(1,2);
	bool res = fun(5);
}

void time_system_test()
{
	cout << "system clock          : ";
	cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;
	cout << "steady clock          : ";
	cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;
	cout << "high resolution clock : ";
	cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;
}


long long getDotProduct(std::vector<int>& v, std::vector<int>& w) {

	auto future1 = std::async(std::launch::deferred, [&] {std::cout << "thread1 id:" << std::this_thread::get_id() << endl; return std::inner_product(v.begin(), v.begin() + v.size() / 4, w.begin(), 0LL); });
	auto future2 = std::async(std::launch::deferred, [&] {std::cout << "thread2 id:" << std::this_thread::get_id() << endl; return std::inner_product(v.begin() + v.size() / 4, v.begin() + v.size() / 2, w.begin() + w.size() / 4, 0LL); });
	auto future3 = std::async(std::launch::deferred, [&] {std::cout << "thread3 id:" << std::this_thread::get_id() << endl; return std::inner_product(v.begin() + v.size() / 2, v.begin() + v.size() * 3 / 4, w.begin() + w.size() / 2, 0LL); });
	auto future4 = std::async(std::launch::deferred, [&] {std::cout << "thread4 id:" << std::this_thread::get_id() << endl; return std::inner_product(v.begin() + v.size() * 3 / 4, v.end(), w.begin() + w.size() * 3 / 4, 0LL); });

	return future1.get() + future2.get() + future3.get() + future4.get();
}

void asyn_function_test()
{
	int NUM = 100000;
	std::cout << std::endl;

	// 从 0 到 100 获取 NUM 个随机数 
	std::random_device seed;

	// 生成随机数
	std::mt19937 engine(seed());

	// 0~100之间均匀分配
	std::uniform_int_distribution<int> dist(0, 100);

	// 放进 vector 容器
	std::vector<int> v, w;
	v.reserve(NUM);
	w.reserve(NUM);
	for (int i = 0; i < NUM; ++i) {
		v.push_back(dist(engine));
		w.push_back(dist(engine));
	}

	// 计算执行时间
	//std::cout << std::this_thread::get_id() << endl;
	std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
	std::cout << "getDotProduct(v,w): " << getDotProduct(v, w) << std::endl;
	std::chrono::duration<double> dur = std::chrono::system_clock::now() - start;
	std::cout << "Parallel Execution: " << dur.count() << std::endl;

	std::cout << std::endl;
}

void future_test()
{
	std::promise<int> promiseObj;
	std::future<int> futureObj = promiseObj.get_future();
	//std::thread th([&](std::promise<int>& promObj) {
	//	std::cout << "Inside Thread" << std::endl;
	//	std::this_thread::sleep_for(std::chrono::seconds(5));
	//	promObj.set_value(35);
	//	std::cout << "setvalue" << endl;
	//}, std::ref(promiseObj));
	//std::cout << futureObj.get() << std::endl;
	//th.join();

	auto ret = std::async(std::launch::async,
		[&](std::promise<int>& promObj)
		{
			std::cout << "Inside Thread" << std::endl;
			std::this_thread::sleep_for(std::chrono::seconds(5));
			promObj.set_value(35);
			std::cout << "setvalue" << endl;
		},
		std::ref(promiseObj));

	std::cout << futureObj.get() << std::endl;
}

void package_task_test()
{
	std::packaged_task<void()> convert([]() {
		throw std::logic_error("will catch in future");
		});
	std::future<void> future = convert.get_future();

	convert(); // 异常不会在此处抛出

	try {
		future.get();
	}
	catch (std::logic_error& e) {
		std::cerr << typeid(e).name() << ": " << e.what() << std::endl;
	}

}

void asyn_call_test()
{
	using namespace std::chrono;

	auto print = [](char c) {
		for (int i = 0; i < 10; i++) {
			std::cout << c;
			std::cout.flush();
			std::this_thread::sleep_for(milliseconds(1));
		}
	};
	// 不同launch策略的效果
	std::launch policies[] = { std::launch::async, std::launch::deferred };
	const char* names[] = { "async   ", "deferred" };
	for (int i = 0; i < sizeof(policies) / sizeof(policies[0]); i++) {
		std::cout << names[i] << ": ";
		std::cout.flush();
		auto f1 = std::async(policies[i], print, '+');
		auto f2 = std::async(policies[i], print, '-');
		f1.get();
		f2.get();
		std::cout << std::endl;
	}
}

class A {
public:
	A() {
		std::cout << std::this_thread::get_id()
			<< " " << __FUNCTION__
			<< "(" << (void*)this << ")"
			<< std::endl;
	}

	~A() {
		std::cout << std::this_thread::get_id()
			<< " " << __FUNCTION__
			<< "(" << (void*)this << ")"
			<< std::endl;
	}

	// 线程中，第一次使用前初始化
	void doSth() {
	}
};

//thread_local A a;
void thread_local_test()
{
	//cout << "-----------" << endl;
	//a.doSth();
	//std::thread t([]() {
	//	std::cout << "Thread: "
	//		<< std::this_thread::get_id()
	//		<< " entered" << std::endl;
	//	a.doSth();
	//});

	//t.join();
}

void once_flag_fun()
{
	cout << "once_flag_fun:" << std::this_thread::get_id() << endl;
}

void call_once_flag_test()
{
	std::once_flag flag;
	for (int i = 0; i < 5; i++)
	{
		auto ret = std::async([&] {std::call_once(flag, once_flag_fun); });
	}
}

void atomic_test()
{
	std::atomic_flag flag = ATOMIC_FLAG_INIT;
	thread thrd[5];
	for (int i = 0; i < 5; i++)
	{
		thrd[i] = thread([&]
			{
				for (int n = 0; n < 500000; n++)
				{

				}
				cout << "thread exit:" << std::this_thread::get_id() << endl;
				if (!flag.test_and_set())
				{
					cout << "thread calc" << std::this_thread::get_id() << endl;
				}
			});
	}

	std::for_each(thrd, thrd + 5, [](thread& td) {td.join(); });
}

void atomic_type_test()
{
	std::atomic_int16_t n = 0;

	//for (int i = 0; i < 10; i++)
	//{
	//	std::async([&] {std::for_each(0, 100, [&] {n.fetch_add(1); }); });
	//}

	//int ret = n.load();

	std::vector<int> v{ 3, 1, 4 };

	auto it = v.end();

	auto nx = std::prev(it, 2);

	std::cout << *nx << '\n';
}

void fun()
{
	cout << endl;
}

template<typename T, typename... Args>
void fun(T&& t, Args&&... args)
{
	//cout << sizeof...(args) << endl;
	cout << t << endl;
	fun(std::forward<Args>(args)...);
}

template<typename T>
std::string to_str(const T& r) {
	std::stringstream ss;
	ss << "\"" << r << "\"";
	return ss.str();
}

template<typename... Args>
void init_vector(std::vector<std::string>& vec, const Args&...args) {
	// 复杂的包扩展方式
	vec.assign({ to_str(args)... });
}

void template_fun_test()
{
	std::vector<std::string> vec;
	init_vector(vec, 1, "hello", "world");
	std::cout << "vec.size => " << vec.size() << std::endl;
	for (auto r : vec)
	{
		std::cout << r << std::endl;
	}

	//fun(1, "hello", "world");
}

void lock_fun_test()
{
	std::mutex m1;
	std::unique_lock<std::mutex> lock;
	{
		std::unique_lock<std::mutex> lo(m1);
		bool res = m1.try_lock();
		lock = std::move(lo);
	}

	bool res = m1.try_lock();
	//std::mutex m2;
	//thread td([&]
	//{
	//	std::lock(m1, m2);
	//	{
	//		bool res = m1.try_lock();
	//		std::lock_guard<std::mutex> lock1(m1, std::adopt_lock);
	//		std::lock_guard<std::mutex> lock2(m2, std::adopt_lock);
	//	}

	//	bool res = m1.try_lock();
	//});
	//td.join();
}

template<typename T, typename TContainer = std::queue<T>>
class thread_safe_queue
{
public:
	thread_safe_queue()
	{
	}
	~thread_safe_queue()
	{

	}
public:
	int size()
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		return m_queue.size();
	}

	void push(const T& val)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		m_queue.push(val);
	}

	T pop()
	{
		std::lock_guard <std::mutex> lock(m_mutex);
		T val = m_queue.front();
		m_queue.pop();

		return val;
	}
private:
	TContainer m_queue;
	std::mutex m_mutex;
};

class student
{
public:
	student(string val)
		:name(val)
	{
		cout << "student constuct" << endl;
	}

	~student()
	{
		cout << "student destruct" << endl;
	}

	student(const student& val)
		:name(val.name)
	{

	}

	student& operator ==(const student& val)
	{
		if (this != &val)
		{
			this->name = val.name;
		}

		return *this;
	}

	student(const student&& val)
		:name(std::move(val.name))
	{

	}

	student&& operator == (const student&& val)
	{
		if (this != &val)
		{
			this->name = std::move(val.name);
		}

		return std::move(*this);
	}

public:
	string get_name()
	{
		return name;
	}
private:
	string name;
};

void thread_safe_queue_test()
{
	thread_safe_queue<std::shared_ptr<student>> queue;

	queue.push(std::make_shared<student>("student1"));

	std::shared_ptr<student> st2 = queue.pop();

	cout << st2->get_name() << endl;
}

template<typename T>
class buffer_queue
{
public:
	buffer_queue(int nMaxCnt)
		:m_nMaxCnt(nMaxCnt)
	{

	}

	~buffer_queue()
	{
		m_buffer.clear();
	}

public:
	void push(T* buf, int nLen)
	{

	}
private:
	std::list<std::shared_ptr<std::vector<T>>> m_buffer;
	int m_nMaxCnt;
};


int arr[2] = { 24, 42 };

auto getArrayRef() -> int(&)[2]
{
	return arr;
}

decltype(arr)& getArrayRef2()
{
	return arr;
}

void map_test()
{
	std::map<int, string> mp({ {1,"a"},{2,"b"},{3,"c"},{4,"d"} });

	//结构化绑定
	for (const auto& [key, val] : mp)
	{
		cout << "key=" << key << "," << "val=" << val << endl;
	}


	std::map<std::string, int> coll{ {"new", 42} };

	auto [iter, result] = coll.emplace("new", 42);
	if (!result)
	{
		//if emplace failed.
		std::cout << "emplace(\"new\", 42) failed" << std::endl;
	}
	else
	{
		std::cout << "emplace(\"new\", 42) successful" << std::endl;

	}

	//auto r2 = getArrayRef();
	//auto [x, y] = getArrayRef();
	//std::shared_ptr<student> sp(new student("a"), [](auto* pt)
	//{
	//	cout << "delete pt   " << typeid(pt).name() << endl;
	//	delete pt;
	//});

	//cout << sp.use_count() << endl;

	//std::weak_ptr<student> ap(sp);
	//cout << sp.use_count() << endl;
	//std::shared_ptr<student> s(ap);
	//cout << sp.use_count() << endl;
}


template <typename T>
std::string asString(T x)
{
	if constexpr (std::is_same_v<T, std::string>) {//第一个判断语句
		std::cout << "satement 1 output: ";
		return x; // statement invalid, if no conversion to string
	}
	else if constexpr (std::is_arithmetic_v<T>) { ////第二个判断语句
		std::cout << "satement 2 output: ";
		return std::to_string(x); // statement invalid, if x is not numeric
	}
	else { ////第三个判断语句
		std::cout << "satement 3 output: ";
		return std::string(x); // statement invalid, if no conversion to string
	}
}

//C++11 仅对lam
auto myFun()
{
	return "";
}

void cpp17_test()
{
	//std::cout << asString(42) << '\n';
	//std::cout << asString(std::string("hello")) << '\n';
	//std::cout << asString("hello") << '\n';
	//std::cout << asString("x2");

	//string str = "0x111";
	//size_t size = 0;
	//int val = std::stoi(str,&size,16);

	int val = 0b1111'0000;

	string myString = "My hello world string";
	if (auto it = myString.find("hello"); it != string::npos)
		cout << it << " - Hello\n";
	if (auto it = myString.find("world"); it != string::npos)
		cout << it << " - World\n";

}

//用户定义字面量 

struct Color
{
	int r, g, b;
};

//定义的字面量转换函数 
//在gcc编译器下注意双引号与后面的_c之间必须有一个空格 vs2014没有该要求
//_c可以任意取名字 一般最好用下划线(_)开头 避免与系统定义的冲突（比方说长整形后缀 L等））
Color operator ""_c(const char* str, size_t n)
{
	//字面常量格式为 r数字g数字b数字
	unsigned char r = 0, g = 0, b = 0;
	for (size_t i = 0; i < n; i++)
	{
		if (str[i] == 'r') r = (unsigned char)atoi(&str[i + 1]);
		else if (str[i] == 'g') g = (unsigned char)atoi(&str[i + 1]);
		else if (str[i] == 'b') b = (unsigned char)atoi(&str[i + 1]);
	}

	return { r, g, b };
}

long double operator""_km(long double val)
{
	return val * 1000;
}

void user_define_test()
{
	//这样使用 将把“r11g12b13”转换成Color结构体 字符串必须用引号括起来 后面必须跟一个_c（前面自定义）的后缀 且与前面的字符串不予许有其他包括空格等字符
	Color c = "r11g12b13"_c;

	long double val = 20.0_km;
}

void string_view_test()
{
	string str = "111222";
	std::string_view sv(str);
	bool res = str.starts_with("2");

}

template<auto Sep = ' ', typename First, typename... Args>
void print(First first, const Args& ... args)
{
	std::cout << first;
	auto outWithSpace = [](auto const& arg)
	{
		std::cout << Sep << arg;
	};

	(outWithSpace(args), ...);
	//(..., outWithSpace(args));
	std::cout << '\n';

}

//C++17之占位符类型作为模板参数
void print_test()
{
	std::string s{ "world" };
	print<'-'>(7.5, "hello", s, "222"); // prints: 7.5-hello-worl
}

template <size_t n, typename... Args>
std::variant<Args...> _tuple_index(size_t i, const std::tuple<Args...>& tpl) {
	if (i == n)
		return std::get<n>(tpl);
	else if (n == sizeof...(Args) - 1)
		throw std::out_of_range("越界.");
	else
		return _tuple_index<(n < sizeof...(Args) - 1 ? n + 1 : 0)>(i, tpl);
}
template <typename... Args>
std::variant<Args...> tuple_index(size_t i, const std::tuple<Args...>& tpl) {
	return _tuple_index<0>(i, tpl);
}

//variant 是 C++17 所提供的变体类型。 variant<X, Y, Z>  是可存放 X, Y, Z 这三种类型数据的变体类型。
//•与C语言中传统的 union 类型相同的是，variant 也是联合(union)类型。即 variant 可以存放多种类型的数据，但任何时刻最多只能存放其中一种类型的数据。
//•与C语言中传统的 union 类型所不同的是，variant 是可辨识的类型安全的联合(union)类型。即 variant 无须借助外力只需要通过查询自身就可辨别实际所存放数据的类型。
//
//v = variant<int, double, std::string>  ，则 v 是一个可存放 int, double, std::string 这三种类型数据的变体类型的对象。
//• v.index()  返回变体类型 v 实际所存放数据的类型的下标。
//变体中第1种类型下标为0，第2种类型下标为1，以此类推。
//• std::holds_alternative<T>(v)  可查询变体类型 v 是否存放了 T 类型的数据。
//• std::get<I>(v)  如果变体类型 v 存放的数据类型下标为 I，那么返回所存放的数据，否则报错。
//std::get_if<I>(&v)  如果变体类型 v 存放的数据类型下标为 I，那么返回所存放数据的指针，否则返回空指针。
//• std::get<T>(v)  如果变体类型 v 存放的数据类型为 T，那么返回所存放的数据，否则报错。
//std::get_if<T>(&v)  如果变体类型 v 存放的数据类型为 T，那么返回所存放数据的指针，否则返回空指针。

void variant_test()
{
	std::tuple tp{ 1,"2",3.3f };
	std::variant<int, const char*, float> val = tuple_index(1, tp);
	int index = val.index();
	val = tuple_index(0, tp);

	int t = std::get<0>(val);
	t = std::get<int>(val);
	auto v = std::get_if<int>(&val);
	bool res = v == nullptr;
	if (std::holds_alternative<const char*>(val)) {
		std::cout << "var1 is " << typeid(int).name() << std::endl;
	}
	else
	{
		cout << "no init" << endl;
	}
	val = "33333";


	std::visit([](auto& v)
		{
			auto t = v;
			cout << v << "---" << endl;
		}, val);

	int n = alignof(long long);
	n = alignof(char[10]);
	n = std::alignment_of<char[10]>::value;
	n = sizeof(char[10]);
}

void option_test()
{
	std::cout << std::endl;

	// C string literal
	std::optional<std::string> opt1(std::in_place, "C++17");                        // 1

	// 5 characters 'C'
	std::optional<std::string> opt2(std::in_place, 5, 'C');                          // 2

	// initializer list
	std::optional<std::string> opt3(std::in_place, { 'C', '+', '+', '1', '7' });      // 3

	// Copy constructor
	std::optional<std::string> opt4(opt3);                                          // 4
	bool res = opt4.has_value();
	std::optional<std::string> opt5;
	res = opt5.has_value();

	std::cout << *opt1 << std::endl;
	std::cout << *opt2 << std::endl;
	std::cout << *opt3 << std::endl;
	std::cout << *opt4 << std::endl;

	std::cout << std::endl;

	std::any t = string("s");

	string s = std::any_cast<string>(t);
	t = 3;

	int v = std::any_cast<int>(t);
	string sr = typeid(t).name();
}

template<typename T, typename... Args>
T* instance(Args&&... args)
{
	return new T(std::forward<Args>(args)...);
}

void instance_test()
{
	student* ps = instance<student>("z");
}

class MyStruct
{
public:
	MyStruct()
	{

	}
	MyStruct(int a, int b) :val((a + b) / 2)
	{

	}
private:
	int val;
};

using aling_A = std::aligned_storage<sizeof(MyStruct), std::alignment_of<MyStruct>::value>::type;

void alignment_test()
{
	aling_A a, b;
	MyStruct* t = new(&a) MyStruct(2, 3);
	b = a;

	MyStruct c = reinterpret_cast<MyStruct&>(b);
}

template<typename T>
class MyOption
{
public:
	using data_t = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
public:
	template<typename... Args>
	MyOption(const T& val)
	{
		Destory();
		Create(val);
	}

	template<typename... Args>
	void Emplace(Args&&... args)
	{
		Destory();
		Create(std::forward<Args>(args)...);
	}

	template<typename... Args>
	void Create(Args&&... args)
	{
		m_bisInit = true;
		new(&m_data) T(std::forward<Args>(args)...);
	}

	void Destory()
	{
		if (m_bisInit)
		{
			((T*)(&m_data))->~T();
		}
	}

	bool has_value()
	{
		return m_bisInit;
	}

	const T& operator *()
	{
		if (m_bisInit)
		{
			return *((T*)(&m_data));
		}

		throw std::exception("no init data!");
	}
private:
	bool m_bisInit = false;
	data_t m_data;
};

void myoption_test()
{
	MyOption<string> op("sss");
	bool res = op.has_value();

	string str = *op;
	//*(&str) = "fds";

	string s = *op;
}

template<typename T>
class my_task;

template<typename R, typename... Args>
class my_task<R(Args...)>
{
public:
	my_task(std::function <R(Args...)>& f)
		:m_fun(f)
	{

	}
	my_task(std::function <R(Args...)>&& f)
		:m_fun(std::move(f))
	{

	}

	R run(Args... args)
	{
		return m_fun(std::forward<Args>(args)...);
	}

	template<typename F>
	auto then(F&& f)->my_task<typename std::invoke_result<F, R>::type(Args...)>
	{
		using return_type = typename std::invoke_result<F, R>::type;
		auto fun = std::move(m_fun);
		return my_task<return_type(Args...)>([fun, &f](Args... args)
			{
				return f(fun(std::forward<Args>(args)...));
			});
	}
private:
	std::function<R(Args...)> m_fun;
};

void task_my_test()
{
	std::function<int(int)> fn = [](int i)->int {return i; };
	my_task<int(int)> ts(fn);

	auto result = ts.then([](int i)->int {return i + 1; }).then([](int i)->int {return i + 2; }).run(1);
}

class base
{
public:
	base()
	{

	}

	virtual ~base()
	{

	}
};

template<typename T>
class baseExt :public base
{
public:
	baseExt(T val)
		:m_val(val)
	{

	}

	virtual ~baseExt()
	{

	}

private:
	T m_val;
};

void type_info_test()
{
	std::type_index index = std::type_index(typeid(string));
	std::type_index index_int = std::type_index(typeid(int));

	std::type_index index_str = std::type_index(typeid(string));

	bool res = index == index_int;
	res = index_str == index;

	std::tuple<string, int, float> tp;

	res = std::is_same<std::tuple_element<0, decltype(tp)>::type, string>::value;
}

template<typename T, typename... Args>
struct type_max_size : public std::integral_constant<int,
	(sizeof(T) > type_max_size<Args...>::value ? sizeof(T) : type_max_size<Args...>::value)>
{};

template<typename T>
struct type_max_size<T> :public std::integral_constant<int, sizeof(T)>
{};

void type_max_size_test()
{
	int size = type_max_size<int, char, long long>::value;
}

template<int N, int... Args>
struct max_int :public std::integral_constant<int,
	(N > max_int<Args...>::value ? N : max_int<Args...>::value)>
{
};
template<int N>
struct max_int<N> :public std::integral_constant<int, N>
{
};

void max_int_test()
{
	int val = max_int<2, 40, 6, 2, 10>::value;
}


template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
//构造器参数的类型来推导
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;

//C++17的变长 using 声明
//• template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
//这是一个类模板的声明。
//• template<class... Ts> ：overloaded 类的模板参数为可变长的参数包 Ts。
//假设 Ts 包含 T1, T2, ..., TN，那么这一句声明可以展开为： template<class T1, class T2, ..., class TN>
//• struct overloaded : Ts... ：overloaded 类的基类为参数包 Ts 内所有的参数类型。
//假设 Ts 包含 T1, T2, ..., TN，那么这一句声明可以展开为： struct overloaded : T1, T2, ..., TN
//• using Ts::operator()...; ：这是一个变长 using 声明。
//假设 Ts 包含 T1, T2, ..., TN，那么这一句声明可以展开为： using T1::operator(), T1::operator(), ..., TN::operator();
//也就是说，overloaded 类的基类即参数包 Ts 内所有的参数类型的函数调用操作符均被 overloaded 类引入了自己的作用域。
//• template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
//这是一个自动推断向导，用于帮助编译器根据 overloaded 构造器参数的类型来推导 overloaded 的模板参数类型。
//这个自动推断向导告诉编译器，如果 overloaded 构造器所有参数的类型的集合为Ts，那么 overloaded 的模板参数类型就是 Ts 所包含的所有类型。
//也就是说如果表达式 a1, a2, ..., an 的类型分别为 T1, T2, ..., TN,
//那么构造器表达式  overloaded{ a1, a2, ..., an }  的类型就是  overloaded<T1, T2, ..., TN> 。
//* overloaded s{
// [](int) {cout << "int" << endl; },
// [](double) {cout << "double" << endl; },
// [](string) {cout << "string" << endl; },
//};
//overloaded 类的实例 s 的构造器包含3个lambda参数，也可以看作3个各自包含一个 operator() 的函数对象。
//根据 overloaded 类的定义，s 对象将继承这3个lambda（函数对象）的 operator() ，也就是说这3个lambda的 operator() 即函数体在 s 对象内部形成重载关系。
//根据 overloaded 类的自动推断向导，s 对象的类型为 overloaded<T1, T2, T3> ，其中T1, T2, T3为3个lambda参数的类型。
//•通过利用 C++17 的新特性变长的 using 声明以及自动推断向导，overloaded类的实例可以简洁并且巧妙地将多个lambda合成一个大的具有多个相互重载的 operator() 的函数对象。
//•overloaded 这个类模板如此有用，实现机制又如此精妙，实在是应该早日纳入标准库中。
struct A1 {
	void f(int) { cout << "A::f(int)" << endl; }
};

struct B1 {
	void f(double) { cout << "B::f(double)" << endl; }
};

struct S : A1, B1 {
	using A1::f, B1::f; // 在 C++17 中多个 using 声明可以通过逗号连接起来，合成一个 using 声明。
};
void overloaded_test()
{
	overloaded s{
		[](int) {cout << "int" << endl; },
		[](double) {cout << "double" << endl; },
		[](string) {cout << "string" << endl; },
	};

}

//string_view 是C++17所提供的用于处理只读字符串的轻量对象。这里后缀 view 的意思是只读的视图。
//•通过调用 string_view 构造器可将字符串转换为 string_view 对象。
//string 可隐式转换为 string_view。
//•string_view 是只读的轻量对象，它对所指向的字符串没有所有权。
//•string_view通常用于函数参数类型，可用来取代 const char* 和 const string& 。
//string_view 代替 const string& ，可以避免不必要的内存分配。
//•string_view的成员函数即对外接口与 string 相类似，但只包含读取字符串内容的部分。
//string_view::substr()的返回值类型是string_view，不产生新的字符串，不会进行内存分配。
//string::substr()的返回值类型是string，产生新的字符串，会进行内存分配。
//•string_view字面量的后缀是 sv。（string字面量的后缀是 s）

void process(string_view sv)
{
	cout << sv << endl;
	for (char ch : sv)
		cout << ch;
	cout << sv[2] << endl;
}
void string_view_test2()
{
	string_view sv = "hello"sv;
	cout << sv << endl;
	string_view sv2 = "hello";
	cout << sv2 << endl;
	string_view sv3 = "hello"s;
	cout << sv3 << endl;
	string_view sv4("hello", 4);
	cout << sv4 << endl;
	process("hello");
	process("hello"s);
}


//•与运行期 if 语句有所不同，编译期 if 语句中的判断条件必须是编译期常量。
//•与预处理期 if 语句有所不同，编译期 if 语句中被丢弃的分支仍然需要进行语法检查。
//•与运行期 if 语句一样，编译期 if 语句的两个分支中任何一个分支只包含一句语句时，该分支的大括号可以省略。

//运行期 if 语句
//if (condition) {
//	statement;
//}
//else if (condition) {
//	statement;
//}
//else {
//	statement;
//}

//预处理 if 语句
//#if condition
//statement;
//#elif condition
//statement;
//#else
//statement;
//#endif

//编译期 if 语句
//if constexpr (condition) {
//	statement;
//}
//else if constexpr (condition) {
//	statement;
//}
//else {
//	statement;
//}

template <typename T>
auto get_value(T t) {
	if constexpr (std::is_pointer_v<T>)
		return *t; // deduces return type to int for T = int*
	else
		return t;  // deduces return type to int for T = int
}
void constexpr_if_test()
{
	int* p;
	//int* p = get_value(p);
}

class placeholder
{
public: // structors 
	virtual ~placeholder() {
	}
public: // queries 
	virtual const std::type_info& type() const = 0;
	virtual placeholder* clone() const = 0;
};

template<typename ValueType>
class holder : public placeholder
{
public: // structors 
	holder(const ValueType& value) : held(value)
	{
	}
public: // queries 
	virtual const std::type_info& type() const {
		return typeid(ValueType);
	}
	virtual placeholder* clone() const {
		return new holder(held);
	}

	ValueType get_value()
	{
		return held;
	}
public: // representation 
	ValueType held;
};


class My_any
{
	placeholder* content_obj;
public:
	template <typename T>
	My_any(T a_right) :content_obj(new holder<T>(a_right))
	{}

	template <typename T>
	My_any& operator = (T a_right) {
		delete content_obj;
		content_obj = new holder<T>(a_right);
		return *this;
	}

	My_any(My_any& a_right)
		: content_obj(a_right.content_obj ?
			a_right.content_obj->clone() : 0)
	{
	}

	template<typename T>
	T any_cast()
	{
		return ((holder<T> *)(content_obj))->get_value();
	}

};

//类型擦除可以达到下面两个目的：

//用类型 S 的接口代表一系列类型 T 的的共性。
//如果 s 是 S 类型的变量，那么，任何 T 类型的的对象都可以赋值给s。
void My_any_test()
{
	My_any any = 3;
	int n = any.any_cast<int>();
}

//时 : 分:秒% H : % M : % S <= = > % T(C++11标准)
//当地时间标准% X
//十二小时制% I(% p <= = > a.m | p.m 或者当地写法)
//
//
//年 - 月 - 日 % Y: % m : % d <= = > % F(C++11标准)
//当期日期标准% x
//一年的第几天% j
//第几周% U(00 - 53) 周日为第一天
//% W(00 - 53) 周一为第一天
//% V(01 - 53) 周一为第一天(C++11标准)
//周一为星期的第一天
//每年的第一星期为包含1月4号的那个星期.
//或者包含第一个星期四那个星期
//星期几% w(0 - 6) % u(1 - 7)(C++11标准)
//星期几% a 单词简写% A 单词全称(当地写法)
//
//原文链接：https ://blog.csdn.net/wangjieest/article/details/7761051
void put_time_test()
{
	std::time_t t = std::time(NULL);
	std::tm tm = *std::localtime(&t);
	std::cout.imbue(std::locale("CHS"));
	std::cout << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << endl;
	std::cout << std::put_time(&tm, "%F %X") << endl;
}

// UTF-8 编码字符理论上可以最多到 6个字节长，但目前全世界的所
// 有文字和符号种类加起来也只要编到 4个字节长就够了。
// 　　UTF-8 是以 8位（即 1个字节）为单元对原始码进行编码（注意一
// 点：这里所讲的原始码都是指Unicode码），并规定：多字节码（2个字
// 节以上才称为多字节）以转换后第1个字节起头的连续“1”的数目（这
// 些连续“1”称为标记位），表示转换成几个字节：“110”连续两个
// “1”，表示转换结果为2个字节，“1110”表示3个字节，而“11110”
// 则表示4个字节……跟随在标记位之后的“0”，其作用是分隔标记位和
// 字符码位。第2～第4个字节的起头两个位固定设置为“10”，也作为标
// 记，剩下的6个位才做为字符码位使用。
// 　　这样，2字节UTF-8码剩下11个字符码位，可用以转换0080～07FF的
// 原始字符码，3字节剩下16个字符码位，可用以转换0800～FFFF的原始字
// 符码，由此类推。编码方式的模板如下：
//
// 原始码（16进制）　UTF－8编码（二进制）
// --------------------------------------------
// 0000 - 007F       0xxxxxxx
// 0080 - 07FF       110xxxxx 10xxxxxx
// 0800 - FFFF       1110xxxx 10xxxxxx 10xxxxxx
// ……
// --------------------------------------------
//
// 　　模板中的“x”表示字符码。
// 　　Ascii码＜007F，编为1个
// 字节的UTF－8码。汉字的 Unicode编码范围为0800－FFFF，所以被编为
// 3个字节的UTF－8码。
// 　　例如“汉”字的Unicode编码是6C49，6C49在0800-FFFF之间，所以
// 要用3个字节的模板：1110wwww 10xxxxyy 10yyzzzz。

//    6    C    4    9
// 0110 1100 0100 1001
// wwww xxxx yyyy zzzz
//     wwww   xxxxyy   yyzzzz
// 1110wwww 10xxxxyy 10yyzzzz。
// 11100110 10110001 10001001
//    E   6    B   1    8   9
//“汉”字的UTF-8编码是E6 B1 89

//gb2312和utf8相互转换：

std::string gb2312_to_utf8(std::string const& strGb2312)
{
	std::vector<wchar_t> buff(strGb2312.size());
#ifdef _MSC_VER
	std::locale loc("zh-CN");
#else
	std::locale loc("zh_CN.GB18030");
#endif
	wchar_t* pwszNext = nullptr;
	const char* pszNext = nullptr;
	mbstate_t state = {};
	int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
		(loc).in(state,
			strGb2312.data(), strGb2312.data() + strGb2312.size(), pszNext,
			buff.data(), buff.data() + buff.size(), pwszNext);

	if (std::codecvt_base::ok == res)
	{
		std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
		return cutf8.to_bytes(std::wstring(buff.data(), pwszNext));
	}

	return "";

}

std::string utf8_to_gb2312(std::string const& strUtf8)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
	std::wstring wTemp = cutf8.from_bytes(strUtf8);
#ifdef _MSC_VER
	std::locale loc("zh-CN");
#else
	std::locale loc("zh_CN.GB18030");
#endif
	const wchar_t* pwszNext = nullptr;
	char* pszNext = nullptr;
	mbstate_t state = {};

	std::vector<char> buff(wTemp.size() * 2);
	int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
		(loc).out(state,
			wTemp.data(), wTemp.data() + wTemp.size(), pwszNext,
			buff.data(), buff.data() + buff.size(), pszNext);

	if (std::codecvt_base::ok == res)
	{
		return std::string(buff.data(), pszNext);
	}
	return "";
}

//https://my.oschina.net/SHIHUAMarryMe/blog/776575
//https://zh.cppreference.com/w/cpp/locale/codecvt_utf8
//https://blog.csdn.net/x_iya/article/details/14500435
void wstring_string_test()
{
	//std::wstring u8Str = L"十" ; //utf8字符.

	//std::string str = "十" ;

	//std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
	//str = convert.to_bytes(u8Str);

	std::wstring str = L"123,我是谁？我爱钓鱼岛！";

	std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;

	std::string narrowStr = conv.to_bytes(str);
	{
		std::ofstream ofs("c:\\test.txt");
		ofs << narrowStr;
	}

	std::wstring wideStr = conv.from_bytes(narrowStr);
	{
		std::locale::global(std::locale("Chinese-simplified"));
		std::wofstream ofs(L"c:\\testW.txt");
		ofs << wideStr;

	}

	//std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	//std::string string = converter.to_bytes(L"这是一个宽字符串");

	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	std::wstring wide_string = converter.from_bytes("\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2");
	//字符串的内容为“字符串”

	//const std::codecvt<wchar_t, char, std::mbstate_t>& cvt =
	//	std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale());

	//std::basic_string<wchar_t> targetStr(u8Str.size() * 2, '\0');
	//std::mbstate_t state = std::mbstate_t{};

	//const char* internT = nullptr;
	//wchar_t* externT = nullptr;


	//cout << "wsting:";
	//for (const wchar_t& c : u8Str) {
	//	std::cout << std::hex << static_cast<unsigned short int>(c) << std::endl;
	//}

	//std::cout << std::endl;
	//cout << "sting:";
	//for (const char& c : str) {
	//	std::cout << std::hex << static_cast<unsigned short int>(c) << std::endl;
	//}

	//std::cout << std::endl;

	////将外部表述转为内部表述.

	//for (const wchar_t& c : targetStr) {
	//	std::cout << std::hex << static_cast<unsigned short int>(c) << std::endl;
	//}

}

void util_test()
{
	std::vector<int> vt(10);
	std::iota(vt.begin(), vt.end(), 1);

	std::vector<int> vt1 = std::move(vt);
	copy(vt1.begin(), vt1.end(), std::ostream_iterator<int>(cout, ","));
}

void random_test()
{
	std::default_random_engine dre;

	//来控制随机数引擎生成0到100之间的整数,平均分别
	std::uniform_int_distribution uid(0, 100);

	dre.seed(time(nullptr));

	cout << "平均分布:";
	for (int i = 0; i < 10; i++)
	{
		cout << uid(dre) << ",";
	}
	cout << endl;

	//控制随机数引擎生成均值为2，标准差为0.25的正态分布数据。
	std::normal_distribution<> nd(2, 0.25);
	cout << "正态分布数据:";
	for (int i = 0; i < 10; i++)
	{
		cout << nd(dre) << ",";
	}
	cout << endl;

	//控制随机数引擎生成布尔值随机数，其中1的概率为0.3
	std::bernoulli_distribution bd(0.3);
	cout << "概率可控的布尔值:";
	for (int i = 0; i < 10; i++)
	{
		cout << bd(dre) << ",";
	}
	cout << endl;
}

enum class type : unsigned char
{
	et_s = 0,
	dt_d = 2
};

//https://blog.csdn.net/qq811299838/article/details/90371604#2.8%20%E6%9E%9A%E4%B8%BE%5B%E7%B1%BB%5D%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%9E%84%E9%80%A0
void enum_class_test()
{
	size_t size = sizeof(type);

	//type t = 2;

	type t = type::et_s;

	int n = (int)t;
}

template<typename ... T>
auto sum(T ... arg)
{
	return (arg + ...);//右折叠
}

template<typename ... T>
double sum_strong(T ... arg)
{
	return (arg + ... + 0);//右折叠
}

template<typename ... T>
double sub1(T ... arg)
{
	return (arg - ...);//右折叠
}

template<typename ... T>
double sub2(T ... arg)
{
	return (... - arg);//左折叠
}

//折叠表达式
void fold_express_test()
{
	int s1 = sum(1, 2, 2, 4, 5);//解包：((((1+)2+)3+)4+)5 = 15
	double s2 = sum(1.1, 2.2, 3.3, 4.4, 5.5, 6.6);
	double s3 = sum(1, 2.2, 3, 4.4, 5);

	double s4 = sub1(5, 2, 1, 1);//解包：((((5-)2-)1-)1) = 1
	double s5 = sub2(5, 2, 1, 1);//解包：(5-(2-(1-(1)))) = 3

	double s6 = sum_strong();//s6 = 0

	std::string str1("he");
	std::string str2("ll");
	std::string str3("o ");
	std::string str4("world");
	std::string str5 = sum(str1, str2, str3, str4);//str5 = "hello world"
}


//模板类的模板参数自动推导
template<class T> struct MyTest {
	explicit MyTest(const T&, ...) noexcept {} // #1
	MyTest(T&&, ...) {} // #2
};

int i;
//MyTest a1 = { i, i }; //错误，不能根据#1推导为右值引用，也不能通过#1实现复制初始化
MyTest a2{ i, i }; //正确，调用#1初始化成功，a2推导为A<int>类型
MyTest a3{ 0, i }; //正确，调用#2初始化成功，a2推导为A<int>类型
MyTest a4 = { 0, i }; //正确，调用#2初始化成功，a2推导为A<int>类型

template<class T> MyTest(const T&, const T&)->MyTest<T&>; // #3
template<class T> explicit MyTest(T&&, T&&)->MyTest<T>; // #4

//A a5 = { 0, 1 }; //错误，#1和#2构造函数结果相同（即冲突）。根据#3推导为A<int&>类型
MyTest a6{ 0, 1 }; //正确，通过#2推断为A<int>类型
//A a7 = { 0, i }; //错误，不能将非静态左值引用绑定到右值。根据#3推导为A<int&>类型
//A a8{ 0, i }; //错误，不能将非静态左值引用绑定到右值。根据#3推导为A<int&>类型

//template<class T>
//struct B {
//
//	template<class U>
//	using TA = T;//定义别名
//
//	template<class U>
//	B(U, TA<U>);//构造函数
//};
//
//B b{ (int*)0, (char*)0 }; //正确，推导为B<char *>类型


template<auto T>
void foo()
{
	std::cout << T << std::endl;
}

void auto_template_param_test()
{
	foo<100>();//输出100
	//foo<int>();//no matching function for call to "foo<int>()"
}

struct ATest {              // abstract class

	virtual int value() = 0;

};



class BTest : public ATest {    // class with specific constructor

	int val_;

public:

	BTest(int i, int j) :val_(i* j) {}

	int value() { return val_; }

	int before() {}

};

void declva_test()
{
	decltype(std::declval<ATest>().value()) a;  // int a
	decltype(std::declval<BTest>().value()) b;  // int b
	decltype(BTest(0, 0).value()) c;   // same as above (known constructor)

	a = b = BTest(10, 2).value();
	bool res = false;

	//逗号表达式
	using type = decltype(std::declval<BTest>().value(), std::true_type());
	string str = typeid(type).name();
}


#define HAS_MEMBER(member)\
template<typename T,typename... Args> struct has_member_##member\
{\
private:\
	template<typename U> static auto Check(int)->decltype(std::declval<U>().member(std::declval<Args>()...),std::true_type());\
	template<typename U> static std::false_type Check(...);\
public:\
	enum{value = std::is_same<decltype(Check<T>(0)), std::true_type>::value};\
}; \

HAS_MEMBER(before)


void has_member_test()
{
	cout << has_member_before<BTest>().value << endl;//是否有无参的before函数
	cout << has_member_before<BTest, int>().value << endl;//是否有参数是int的before函数
}

//class DllParser
//{
//public:
//
//	DllParser() :m_hMod(nullptr)
//	{
//	}
//
//	~DllParser()
//	{
//		UnLoad();
//	}
//
//	bool Load(const string& dllPath)
//	{
//		m_hMod = LoadLibraryA(dllPath.data());
//		if (nullptr == m_hMod)
//		{
//			printf("LoadLibrary failed\n");
//			return false;
//		}
//
//		return true;
//	}
//
//	bool UnLoad()
//	{
//		if (m_hMod == nullptr)
//			return true;
//
//		auto b = FreeLibrary(m_hMod);
//		if (!b)
//			return false;
//
//		m_hMod = nullptr;
//		return true;
//	}
//
//	template <typename T>
//	std::function<T> GetFunction(const string& funcName)
//	{
//		auto it = m_map.find(funcName);
//		if (it == m_map.end())
//		{
//			auto addr = GetProcAddress(m_hMod, funcName.c_str());
//			if (!addr)
//				return nullptr;
//			m_map.insert(std::make_pair(funcName, addr));
//			it = m_map.find(funcName);
//		}
//
//		return std::function<T>((T*)(it->second));
//	}
//
//	template <typename T, typename... Args>
//	typename auto ExcecuteFunc(const std::string& funcName, Args&&... args)->decltype(std::function<T>(Args...))
//	{
//		auto f = GetFunction<T>(funcName);
//		if (f == nullptr)
//		{
//			std::string s = "can not find this function " + funcName;
//			throw std::exception(s.c_str());
//		}
//
//		return f(std::forward<Args>(args)...);
//	}
//
//private:
//	HMODULE m_hMod;
//	std::map<string, FARPROC> m_map;
//};

//c++11提供了另一个traits——result_of
int fn(int) { return int(); };
typedef int(&fn_ref)(int);
typedef int(*fn_ptr)(int);
struct fn_class {

	int operator()(int i) {

		return i;

	}

};

void result_of_test()
{
	//	需要注意 std::result_of<Fn(ArgTypes)> 要去Fn为一个可调用对象，而函数类型不是一个可调用对象，因此，不能使用
	//	typedef std::result_of<decltype(fn)(int)>::type A :  //错误
	//	需要先将fn转换为一个可调用对象类型，比如：
	//	typedef std::result_of<decltype(fn) & (int)>::type A;
	//	typedef std::result_of<decltype(fn) * (int)>::type B;

		//typedef std::result_of<std::decay<decltype(fn)>::type(int)>::type C;
		//typedef std::result_of<decltype(fn) & (int)>::type A;  //int

		//typedef std::result_of<fn_ref(int)>::type B;        //int

		//typedef std::result_of<fn_ptr(int)>::type C;        //int

		//typedef std::result_of<fn_class(int)>::type D;      //int

}

void tuple_test()
{
	std::tuple<int, double, std::string> t(64, 128.0, "Caroline");
	std::tuple<std::string, std::string, int> t2 =
		std::make_tuple("Caroline", "Wendy", 1992);

	auto [x, y, z] = t;

	//返回元素个数  
	size_t num = std::tuple_size<decltype(t)>::value;
	std::cout << "num = " << num << std::endl;

	//获取第1个值的元素类型  
	std::tuple_element<1, decltype(t)>::type cnt = std::get<1>(t);
	std::cout << "cnt = " << cnt << std::endl;

	//比较  
	std::tuple<int, int> ti(24, 48);
	std::tuple<double, double> td(28.0, 56.0);
	bool b = (ti < td);
	std::cout << "b = " << b << std::endl;


}

//SFINAE 意为“匹配失败并不是错误”
void common_test()
{
	//base* p = new baseExt<student>(student("a"));
	//thread_test();
	//promise_test();
	//function_test();
	//time_system_test();
	//asyn_function_test();
	//future_test();
	//package_task_test();
	//asyn_call_test();
	//thread_local_test();
	//call_once_flag_test();
	//atomic_test();
	//atomic_type_test();
	//template_fun_test();
	//lock_fun_test();
	//thread_safe_queue_test();
	//map_test();
	//cpp17_test();
	//string_view_test();
	//user_define_test();
	//print_test();
	variant_test();
	option_test();
	//instance_test();
	//alignment_test();
	//myoption_test();
	//task_my_test();
	//type_info_test();
	//type_max_size_test();
	//max_int_test();
	//overloaded_test();
	//My_any_test();
	//put_time_test();
	//wstring_string_test();
	//util_test();
	//random_test();
	//enum_class_test();
	//fold_express_test();
	//auto_template_param_test();
	//declva_test();
	//has_member_test();
	//result_of_test();
	//tuple_test();
}
}

